package org.example.service.impl;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.example.entity.SysDept;
import org.example.mapper.DemoMapper;
import org.example.mapper.SysTestConfigMapper;
import org.example.mapper.TableColumnMapper;
import org.example.pojo.*;
import org.example.service.DemoService;
import org.example.service.TestHttpMethod;
import org.example.util.HttpServiceProxy;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author wxm
 * @date 2025/2/12 10:08
 */
@Service
@Slf4j
public class DemoServiceImpl extends ServiceImpl<DemoMapper, DemoVo> implements DemoService {
    @Autowired
    private DemoMapper demoMapping;
    @Autowired
    private SysTestConfigMapper sysTestConfigMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private TableColumnMapper tableColumnMapper;
    private final TestHttpMethod testHttpMethod = HttpServiceProxy.create(TestHttpMethod.class);

    @Value("${jsonFile.path}")
    private String jsonFilePath;
    @Value("${table.module}")
    private String tableModule;
    @Value("${redisData.timeout}")
    private Integer redisDataTimeout;

    @Override
    public JSONObject demo(String path) {
        // 创建一个JSON解析器
        JSONParser jsonParser = new JSONParser();
        try (FileReader reader = new FileReader(jsonFilePath + path + ".json")) {
            // 解析JSON文件
            Object obj = jsonParser.parse(reader);
            // 将解析后的对象转换为JSONObject
            JSONObject jsonObject = JSONObject.parseObject(obj.toString());
            String dataPath = jsonObject.get("path").toString();
            JSONArray tables = jsonObject.getJSONArray("tables");
            for (int i = 0; i < tables.size(); i++) {
                JSONObject table = tables.getJSONObject(i);
                JSONArray columns = table.getJSONArray("columns");
                for (int j = 0; j < columns.size(); j++) {
                    JSONObject column = columns.getJSONObject(j);
                    if (column.get("inputType").toString().equals("selection")) {
                        String num = column.get("num").toString();
                        List<SysTestConfigDto> strings = sysTestConfigMapper.selectList(dataPath, num);
                        JSONObject formType = column.getJSONObject("formType");
                        formType.put("data", strings);
                    }
                }
            }
            return jsonObject;
        } catch (IOException e) {
            log.error("读取JSON文件失败,{}", e.getMessage());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return new JSONObject();
    }

    @Override
    public JSONObject create(JSONObject jsonObject) {
        String path = jsonObject.get("path").toString();
        // 指定文件名
        String fileName = path + ".json";
        // 指定内容
        String content = jsonObject.toString();
        // 创建文件并写入内容
        writeFile(jsonFilePath + fileName, content);
        System.out.println("文件创建成功: " + jsonFilePath + fileName);
        return new JSONObject();
    }

    @Override
    public List<DemoVo> select() {
        return demoMapping.getUserNames();
    }

    @Override
    public List<String> allTableName(String keyword, String tableModule) {
        try {
            String redisData = redisTemplate.opsForValue().get(tableModule);
            List<String> tableNameList;
            if (StringUtils.isEmpty(redisData)) {
                synchronized (this) {
                    redisData = redisTemplate.opsForValue().get(tableModule);
                    if (StringUtils.isEmpty(redisData)) {
                        tableNameList = tableColumnMapper.selectAllTableName(tableModule);
                        Collections.sort(tableNameList);
                        redisTemplate.opsForValue().set(tableModule, JSONObject.toJSONString(tableNameList), redisDataTimeout, TimeUnit.SECONDS);
                    } else {
                        tableNameList = parseRedisData(redisData);
                    }
                }
            } else {
                tableNameList = parseRedisData(redisData);
            }

            if (keyword == null || keyword.isEmpty()) {
                return tableNameList;
            }

            // 执行模糊查询
            List<String> result = fuzzySearch(tableNameList, keyword);
            Collections.sort(result);
            return result;
        } catch (Exception e) {
            log.error("Error occurred while fetching or parsing data from Redis", e);
            return Collections.emptyList();
        }
    }

    private List<String> parseRedisData(String redisData) {
        try {
            JSONArray jsonArray = JSONArray.parseArray(redisData);
            return jsonArray.toJavaList(String.class);
        } catch (Exception e) {
            log.error("Error parsing Redis data: " + redisData, e);
            return Collections.emptyList();
        }
    }


    @Override
    public List<TableColumnDto> getAllColumns(String tableName) {
        List<TableColumnDto> tableColumns = tableColumnMapper.selectTableColumns(tableName);
        List<TableColumnDto> tableComments = tableColumnMapper.selectTableComments(tableName);
        tableColumns.forEach(tableColumnDto -> {
            for (TableColumnDto tableComment : tableComments) {
                if (tableColumnDto.getColumnName().equals(tableComment.getColumnName())) {
                    tableColumnDto.setComments(tableComment.getComments());
                }
            }
            tableColumnDto.setNotNull(tableColumnDto.getNULLABLE().equals("N"));
        });
        return tableColumns;
    }

    @Override
    public void saveConfig(TableConfigVo tableConfig) {
        TableConfigDto tableConfigDto = new TableConfigDto();
        tableConfigDto.setUrl(tableConfig.getUrl());
        tableConfigDto.setTableName(tableConfig.getTableName());
        tableConfigDto.setContent(tableConfig.getConfig().toString());
        tableColumnMapper.saveConfig(tableConfigDto);
    }

    @Override
    public List<Map<String, Object>> selectDataByTableName(String tableName) {
        return tableColumnMapper.selectDataByTableName(tableModule + "." + tableName);
    }

    @Override
    public List<Map<String, Object>> selectDataByCondition(String tableName, String rows, Boolean isSort, String sortColumn) {
        return tableColumnMapper.selectDataByCondition(tableModule + "." + tableName, rows, isSort, sortColumn);
    }

    @Override
    public List<Map<String, Object>> relevanceSelect(JSONObject jsonObject) {
        String tableName = jsonObject.get("tableName").toString();
        JSONArray excel = jsonObject.getJSONArray("excel");
        JSONArray system = jsonObject.getJSONArray("system");
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < system.size(); i++) {
            builder.append(system.get(i));
            if (i < system.size() - 1) {
                builder.append(",");
            }
        }
        List<Map<String, Object>> dataList = new ArrayList<>();
        JSONObject excelJson = JSONObject.parseObject(JSONObject.toJSONString(excel.get(0)));
        Set<String> keyed = excelJson.keySet();
        for (String key : keyed) {
            JSONArray jsonArray = excelJson.getJSONArray(key);
            dataList = tableColumnMapper.relevanceSelect(builder.toString(), key, jsonArray, tableModule + "." + tableName);
        }
        return dataList;
    }

    @Override
    public List<Map<String, Object>> testAop() {
        return tableColumnMapper.selectAllData();
    }

    @Override
    // @GetForHttp(url = "http://127.0.0.1:8080/api/testGetUrl", param = {"fileName"}, body = {"1"})
    // @PostForHttp(url = "http://127.0.0.1:8080/api/testPostUrl", param = {"fileName", "url"}, body = {"1", "2"}, contentType = "application/x-www-form-urlencoded")
    public List<SysDept> testPage(TestPage testPage) {
        IPage<SysDept> page = new Page<>(testPage.getPageIndex(), testPage.getPageSize());
        return tableColumnMapper.selectPageVo(page);
    }

    @Override
    public String testHttpGet() {
        String httpGet = testHttpMethod.testHttpGet("test");
        System.out.println("httpGet = " + httpGet);
        String httpPost = testHttpMethod.testHttpPost("test-1", "test-2");
        System.out.println("httpPost = " + httpPost);
        TestAopBody testAopBody = new TestAopBody();
        testAopBody.setName("test-3");
        testAopBody.setAge(3);
        String testHttpBody = testHttpMethod.testHttpBody(testAopBody);
        System.out.println("testHttpBody = " + testHttpBody);
        return httpGet + "--" + httpPost + "--" + testHttpBody;
    }

    @Override
    @Transactional
    public String importExcel(MultipartFile file) {
        try {
            // 将 MultipartFile 转换为 File
            File tempFile = convertMultipartFileToFile(file);
            List<DemoVo> demoList = new ArrayList<>();
            EasyExcel.read(tempFile, ImportExcelDto.class, new AnalysisEventListener<ImportExcelDto>() {
                @Override
                public void invoke(ImportExcelDto data, AnalysisContext context) {
                    DemoVo demoVo = new DemoVo();
                    // demoVo.setId(data.getId());
                    demoVo.setCode(data.getCode());
                    demoVo.setName(data.getName());
                    demoList.add(demoVo);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 所有数据解析完成后执行的操作
                    System.out.println("所有数据解析完成");
                }
            }).sheet().doRead();
            saveBatch(demoList, 1000);
            return "导入成功";
        } catch (IOException e) {
            e.printStackTrace();
            return "导入失败: " + e.getMessage();
        }
    }

    @Override
    public List<String> getAllObjects() {
        return demoMapping.getAllObjects();
    }

    private File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
        File tempFile = File.createTempFile("temp", null);
        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
            fos.write(multipartFile.getBytes());
        }
        return tempFile;
    }


    /**
     * 模糊查询方法
     *
     * @param list    要查询的用户名称列表
     * @param keyword 模糊查询的关键词
     * @return 匹配的用户名称列表
     */
    public static List<String> fuzzySearch(List<String> list, String keyword) {
        List<String> result = new ArrayList<>();
        for (String username : list) {
            // 使用contains()方法进行模糊匹配，忽略大小写
            if (username.toLowerCase().contains(keyword.toLowerCase())) {
                result.add(username);
            }
        }
        return result;
    }

    /**
     * 写文件
     *
     * @param filePath 文件路径
     * @param content  内容
     */
    private static void writeFile(String filePath, String content) {
        // 创建文件对象
        File file = new File(filePath);
        // 创建父目录（如果不存在）
        file.getParentFile().mkdirs();
        // 使用BufferedWriter写入文件
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            writer.write(content);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
